﻿' ******************************************************************************
' ** 
' **  Yahoo! Managed
' **  Written by Marius Häusler 2011
' **  It would be pleasant, if you contact me when you are using this code.
' **  Contact: YahooFinanceManaged@gmail.com
' **  Project Home: http://code.google.com/p/yahoo-finance-managed/
' **  
' ******************************************************************************
' **  
' **  Copyright 2011 Marius Häusler
' **  
' **  Licensed under the Apache License, Version 2.0 (the "License");
' **  you may not use this file except in compliance with the License.
' **  You may obtain a copy of the License at
' **  
' **    http://www.apache.org/licenses/LICENSE-2.0
' **  
' **  Unless required by applicable law or agreed to in writing, software
' **  distributed under the License is distributed on an "AS IS" BASIS,
' **  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
' **  See the License for the specific language governing permissions and
' **  limitations under the License.
' ** 
' ******************************************************************************


Namespace YahooManaged.Finance.API

    ''' <summary>
    ''' Provides methods for downloading company information.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class CompanyInfoDownload
        Inherits Base.Download

        Friend ReadOnly mFinanceHelper As New FinanceHelper
        Private mXmlParser As New ImportExport.XML

        ''' <summary>
        ''' Raises if an asynchronous download of company information completes.
        ''' </summary>
        ''' <param name="sender">The event raising object</param>
        ''' <param name="ea">The event args of the asynchronous download</param>
        ''' <remarks></remarks>
        Public Event AsyncDownloadCompleted(ByVal sender As Base.Download, ByVal ea As CompanyInfoDownloadCompletedEventArgs)

        ''' <summary>
        ''' Downloads company informations with passed ID.
        ''' </summary>
        ''' <param name="managedID">The managed ID of the company</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function Download(ByVal managedID As IID) As CompanyInfoResponse
            If managedID Is Nothing Then Throw New ArgumentNullException("managedID", "The passed ID is null.")
            Return Me.Download(managedID.ID)
        End Function
        ''' <summary>
        ''' Downloads company informations with passed ID.
        ''' </summary>
        ''' <param name="unmanagedID">The unmanaged ID of the company</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function Download(ByVal unmanagedID As String) As CompanyInfoResponse
            If unmanagedID = String.Empty Then Throw New ArgumentNullException("unmanagedID", "The passed ID is empty.")
            Return Me.Download(New String() {unmanagedID})
        End Function
        ''' <summary>
        ''' Downloads company informations with passed IDs.
        ''' </summary>
        ''' <param name="ids">The managed list of IDs of the companies</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function Download(ByVal ids As IEnumerable(Of IID)) As CompanyInfoResponse
            If ids Is Nothing Then Throw New ArgumentNullException("ids", "The passed list is null.")
            Return Me.Download(mFinanceHelper.IIDsToStrings(ids))
        End Function
        ''' <summary>
        ''' Downloads company information with passed IDs.
        ''' </summary>
        ''' <param name="ids">The unmanaged list of IDs of the companies</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function Download(ByVal ids As IEnumerable(Of String)) As CompanyInfoResponse
            If ids Is Nothing Then Throw New ArgumentNullException("ids", "The passed list is null.")
            Return Me.ToResponse(MyBase.DownloadStream(Me.DownloadURL(mHelper.EnumToArray(ids))))
        End Function

        ''' <summary>
        ''' Starts an asynchronous download of company informations with passed ID.
        ''' </summary>
        ''' <param name="managedID">The managed ID of the company</param>
        ''' <param name="userArgs">Individual user argument</param>
        ''' <remarks></remarks>
        Public Overloads Sub DownloadAsync(ByVal managedID As IID, Optional ByVal userArgs As Object = Nothing)
            If managedID Is Nothing Then Throw New ArgumentNullException("managedID", "The passed ID is null.")
            Me.DownloadAsync(managedID.ID, userArgs)
        End Sub
        ''' <summary>
        ''' Starts an asynchronous download of company informations with passed ID.
        ''' </summary>
        ''' <param name="unmanagedID">The unmanaged ID of the company</param>
        ''' <param name="userArgs">Individual user argument</param>
        ''' <remarks></remarks>
        Public Overloads Sub DownloadAsync(ByVal unmanagedID As String, Optional ByVal userArgs As Object = Nothing)
            If unmanagedID = String.Empty Then Throw New ArgumentNullException("unmanagedID", "The passed ID is null.")
            Me.DownloadAsync(New String() {unmanagedID}, userArgs)
        End Sub
        ''' <summary>
        ''' Starts an asynchronous download of company informations with passed IDs.
        ''' </summary>
        ''' <param name="managedIDs">The managed list of IDs of the companies</param>
        ''' <param name="userArgs">Individual user argument</param>
        ''' <remarks></remarks>
        Public Overloads Sub DownloadAsync(ByVal managedIDs As IEnumerable(Of IID), Optional ByVal userArgs As Object = Nothing)
            If managedIDs Is Nothing Then Throw New ArgumentNullException("managedIDs", "The passed list is null.")
            Me.DownloadAsync(mFinanceHelper.IIDsToStrings(managedIDs), userArgs)
        End Sub
        ''' <summary>
        ''' Starts an asynchronous download of company informations with passed IDs.
        ''' </summary>
        ''' <param name="unmanagedIDs">The unmanaged list IDs of the companies</param>
        ''' <param name="userArgs">Individual user argument</param>
        ''' <remarks></remarks>
        Public Overloads Sub DownloadAsync(ByVal unmanagedIDs As IEnumerable(Of String), Optional ByVal userArgs As Object = Nothing)
            If unmanagedIDs Is Nothing Then Throw New ArgumentNullException("unmanagedIDs", "The passed list is null.")
            Dim args As New AsyncDownloadArgs(userArgs, mHelper.EnumToArray(unmanagedIDs))
            MyBase.DownloadStreamAsync(Me.DownloadURL(args.IDs), args)
        End Sub

        ''' <summary>
        ''' Default constructor
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New()
        End Sub

        Private Sub DownloadAsync_Completed(ByVal sender As Base.Download, ByVal e As Base.StreamDownloadCompletedEventArgs) Handles MyBase.AsyncStreamDownloadCompleted
            If e IsNot Nothing AndAlso e.UserArgs IsNot Nothing AndAlso TypeOf e.UserArgs Is AsyncDownloadArgs Then
                Dim dlArgs As AsyncDownloadArgs = DirectCast(e.UserArgs, AsyncDownloadArgs)
                Dim args As New CompanyInfoDownloadCompletedEventArgs(dlArgs.UserArgs, Me.ToResponse(e.Response), dlArgs.IDs)
                RaiseEvent AsyncDownloadCompleted(Me, args)
            End If
        End Sub

        Private Function DownloadURL(ByVal unmanagedIDs() As String) As String
            If unmanagedIDs IsNot Nothing AndAlso unmanagedIDs.Length > 0 Then
                Dim whereClause As New Text.StringBuilder()
                whereClause.Append("symbol in (")
                For Each id As String In unmanagedIDs
                    whereClause.Append(""""c)
                    whereClause.Append(mHelper.CleanYqlParam(id))
                    whereClause.Append(""",")
                Next
                whereClause.Remove(whereClause.Length - 1, 1)
                whereClause.Append(")"c)
                Return mHelper.YqlUrl("*"c, "yahoo.finance.stocks", whereClause.ToString, Nothing, False)
            Else
                Return ""
            End If
        End Function

        Private Function ToResponse(ByVal resp As Base.StreamResponse) As CompanyInfoResponse
            Dim companies As New List(Of CompanyInfoData)
            Dim culture As New Globalization.CultureInfo("en-US")
            Dim results = mHelper.GetResultsFromXml(resp.Result, "stock")
            For Each node In results
                Dim c As CompanyInfoData = mXmlParser.ToCompanyData(node, culture)
                If c IsNot Nothing Then companies.Add(c)
            Next
            Return New CompanyInfoResponse(resp.Connection, companies.ToArray)
        End Function


        Private Class AsyncDownloadArgs
            Inherits Base.DownloadEventArgs
            Public IDs() As String
            Public Sub New(ByVal userArgs As Object, ByVal comp() As String)
                MyBase.New(userArgs)
                Me.IDs = comp
            End Sub
        End Class

    End Class

    ''' <summary>
    ''' Provides information and response of an asynchronous company information download.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class CompanyInfoDownloadCompletedEventArgs
        Inherits Base.DownloadCompletedEventArgs

        Private mIDs() As String

        ''' <summary>
        ''' Gets the used IDs for downloading.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property IDs() As String()
            Get
                Return mIDs
            End Get
        End Property
        ''' <summary>
        ''' Gets the response with comapny information.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overloads ReadOnly Property Response() As CompanyInfoResponse
            Get
                Return DirectCast(MyBase.Response, CompanyInfoResponse)
            End Get
        End Property

        Friend Sub New(ByVal userArgs As Object, ByVal resp As CompanyInfoResponse, ByVal ids() As String)
            MyBase.New(userArgs, resp)
            mIDs = ids
        End Sub

    End Class

    ''' <summary>
    ''' Provides connection information and downloaded company data.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class CompanyInfoResponse
        Inherits Base.Response

        ''' <summary>
        ''' Gets the received company informations.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overloads ReadOnly Property Result() As CompanyInfoData()
            Get
                Return TryCast(MyBase.Result, CompanyInfoData())
            End Get
        End Property

        Friend Sub New(ByVal info As Base.ConnectionInfo, ByVal result As CompanyInfoData())
            MyBase.New(info, result)
        End Sub

    End Class

End Namespace